#include"Menu.h"
Menu::Menu()
{}
Menu::Menu(int no, char **str)
{
	int i;
	NoOfItems = no;
	for ( i = 0; i < NoOfItems; i++ )
	{
		MenuItems[i] = (char *) malloc(STR);
		strcpy(MenuItems[i], str[i]);
	}
}
/****************************************************************************
 *  Name       : createMenu
 *  Parameters : Number of Menu Items
 *               String array containing the MenuItems
 *  Returns    : Nothing
 *  Purpose    : To reinitialize an existing Menu object with new values.
 ****************************************************************************/
void Menu::createMenu(int no, char **str)
{
	int i;
	NoOfItems = no;
	for ( i = 0; i < NoOfItems; i++ )
	{
		MenuItems[i] = (char *) malloc(STR);
		strcpy(MenuItems[i], str[i]);
	}
}
/****************************************************************************
 *  Name       : calculateMenuWidth
 *  Parameters : None
 *  Returns    : Nothing
 *  Purpose    : To caculate MenuWidth based on the maximum length of the
 *               MenuItems plus the 3 spaces on each side.
 ****************************************************************************/
void Menu::calculateMenuWidth()
{
	int i, len;
	MenuWidth = strlen(MenuItems[0]);
	for ( i = 1; i < NoOfItems; i++ )
	{
		len = strlen(MenuItems[i]);
		if ( MenuWidth < len )
			MenuWidth = len;
	}
	MenuWidth += 6; // Account for border char and 2 spaces both sides (2 * 2)
}
/****************************************************************************
 *  Name       : highlightItem
 *  Parameters : Index of MenuItem to be highlighted
 *               Color of the highlight
 *  Returns    : Nothing
 *  Purpose    : To highlight the MenuItem specified by the Index.
 ****************************************************************************/
void Menu::highlightItem(int index, int hCol = M_HIL)
{
	if ( index < NoOfItems )
	{
		int i, end;
		end = x + MenuWidth - 2; // to remove the border char and 2 fillers
		for ( i = x + 3; i < end; i++ )
			highlightChar(i, y + index + 1, hCol);
	}
}
/****************************************************************************
 *  Name       : setXY
 *  Parameters : X position
 *               Y position
 *  Returns    : Nothing
 *  Purpose    : Sets the top left corner of the Menu.
 ****************************************************************************/
void Menu::setXY(int xVal, int yVal)
{
	x = xVal;
	y = yVal;
}
/****************************************************************************
 *  Name       : getHotKeys
 *  Parameters : None
 *  Returns    : Nothing
 *  Purpose    : Used to determine the hotkeys based on the '&' present
 *               before a hotkey.
 ****************************************************************************/
void Menu::getHotKeys()
{
	int i, j, len, found = 0;
	HotKeys = (char *) malloc(NoOfItems * sizeof(char));
	for ( i = 0; i < NoOfItems; i++ )
	{
		found = 0;
		len = strlen(MenuItems[i]);
		for ( j = 0; (j < len) && !found ; j++ )
		{
			if ( MenuItems[i][j] == '&' )
			{
				HotKeys[i] = toupper(MenuItems[i][j + 1]);
				found = 1;
			}
			else if ( MenuItems[i][j] == '\0' )
			{
				HotKeys[i] = '\1';
				found = 1;
			}
		} // endfor j
	} // endfor i
}
/****************************************************************************
 *  Name       : notify
 *  Parameters : None
 *  Returns    : Nothing
 *  Purpose    : Notifies the Menu that the top left coordinates and the
 *               MenuItems have been added.  So the Menu must store the
 *               hotkeys and calculate MenuWidth. (Must be called either
 *               showMenu() or handleMenu() are called)
 ****************************************************************************/
void Menu::notify()
{
	getHotKeys();
	calculateMenuWidth();
}
/****************************************************************************
 *  Name       : getMenuCoords
 *  Parameters : Pointer to a Rectangle
 *  Returns    : Nothing
 *  Purpose    : Stores the current Menu Rectangle coordinates into the
 *               pointer variable that is passed.
 ****************************************************************************/
void Menu::getMenuCoords(Rectangle *win)
{
	win->left   = x;
	win->top    = y;
	win->right  = x + MenuWidth;
	win->bottom = NoOfItems + 2;
}
/****************************************************************************
 *  Name       : inMenu
 *  Parameters : X position
 *               Y position
 *  Returns    : Index of the MenuItem on success, -1 otherwise
 *  Purpose    : Checks if the passed coordinate is inside the Menu.
 ****************************************************************************/
int Menu::inMenu(int Xpos, int Ypos)
{
	int r, b;
	r = (x + MenuWidth + 2) - 1;
	b = NoOfItems + 2;
	if ( Xpos >= (x + 2) && Xpos <= r && Ypos >= (y + 1) && Ypos <= b )
		return (Ypos - (y + 1));
	return -1;
}
/****************************************************************************
 *  Name       : showMenu
 *  Parameters : None
 *  Returns    : Nothing
 *  Purpose    : Displays the Menu on the screen.
 ****************************************************************************/
void Menu::showMenu()
{
	int i, r, b;
	r = x + MenuWidth;
	b = NoOfItems + 2;
	drawSingleBox(x, y, r, b, M_TXT);
	fillBox(x + 2, y + 1, r - 1, b, M_TXT);
	for ( i = 0; i < NoOfItems; i++ )
		putStr(x + 3, y + i + 1, MenuItems[i], M_TXT, M_HOT);
	//cout<<endl<<x<<", "<<y<<endl<<MenuWidth;
}
/****************************************************************************
 *  Name       : handleMenu
 *  Parameters : None
 *  Returns    : Index of the selected MenuItem or -1 if ESC is pressed
 *  Purpose    : Handles the Menu events.
 ****************************************************************************/
int Menu::handleMenu()
{
	int hLen, i, ch, choice = 0;
	highlightItem(choice);
	while ( 1 )
	{
			if ( kbhit() )
		{
			ch = getKey();
			switch ( ch )
			{
				case    UP: highlightItem(choice, M_TXT >> 4); // restore original
										choice = (choice == 0) ? NoOfItems - 1 : --choice;
										highlightItem(choice);
										break;
				case  DOWN: highlightItem(choice, M_TXT >> 4); // restore original
										choice = (choice == (NoOfItems-1)) ? 0 : ++choice;
										highlightItem(choice);
										break;
				case ENTER: return choice;
				case   ESC: return -1;
				case RIGHT: return RIGHT;
				case  LEFT: return LEFT;
				default:    hLen = strlen(HotKeys);
									ch = toupper(ch);
									for ( i = 0; i < hLen; i++ )
									{
										if ( HotKeys[i] == '\1' )
											continue;
										if ( ch == HotKeys[i] )
											return i;
									}
			} // endswitch
		} // end kbhit
	}
	//return -1; // invalid (must never come here)
}
